package me.zhengjie.modules.website.service.impl;

import me.zhengjie.modules.website.domain.VisitReservationTable;
import me.zhengjie.modules.website.exception.DuplicateReservationException;
import me.zhengjie.modules.website.repository.VisitReservationTableRepository;
import me.zhengjie.modules.website.repository.VisitReservationTableSpecifications;
import me.zhengjie.modules.website.service.VisitReservationTableService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import me.zhengjie.modules.website.domain.PageResult;

import javax.persistence.criteria.Predicate;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author system
 * @since 2024-10-23 22:20:17
 */
@Service
public class VisitReservationTableServiceImpl implements VisitReservationTableService {

    @Autowired
    private VisitReservationTableRepository visitReservationTableRepository;

    @Override
    public PageResult<VisitReservationTable> findPage(
            VisitReservationTable visitReservationTable,
            LocalDateTime startDate,
            LocalDateTime endDate,
            Pageable pageable) {

        Page<VisitReservationTable> page = visitReservationTableRepository.findAll((root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // 通过反射遍历 VisitReservationTable 的所有字段，过滤静态字段
            for (Field field : VisitReservationTable.class.getDeclaredFields()) {
                field.setAccessible(true); // 允许访问私有字段

                // 跳过静态字段
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }

                try {
                    Object value = field.get(visitReservationTable); // 获取字段值
                    if (value != null) { // 如果字段不为空，添加查询条件
                        predicates.add(criteriaBuilder.equal(root.get(field.getName()), value));
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            // 时间范围条件
            if (startDate != null) {
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("createTime"), Timestamp.valueOf(startDate)));
            }
            if (endDate != null) {
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("createTime"), Timestamp.valueOf(endDate)));
            }

            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        }, pageable);

        PageResult<VisitReservationTable> result = new PageResult<>();
        result.setContent(page.getContent());
        result.setTotalElements(page.getTotalElements());
        return result;
    }


    @Override
    public PageResult<VisitReservationTable> findPage(VisitReservationTable visitReservationTable, Pageable pageable) {
        Page<VisitReservationTable> page = visitReservationTableRepository.findAll(VisitReservationTableSpecifications.queryList(visitReservationTable), pageable);
        PageResult<VisitReservationTable> result = new PageResult();
        result.setContent(page.getContent());
        result.setTotalElements(page.getTotalElements());
        return result;
    }

    @Override
    public List<VisitReservationTable> findList(VisitReservationTable visitReservationTable) {
        return visitReservationTableRepository.findAll(VisitReservationTableSpecifications.queryList(visitReservationTable));
    }

    @Override
    public VisitReservationTable findById(Long id) {
        return visitReservationTableRepository.findById(id).orElse(null);
    }

  /*  @Override
    public VisitReservationTable insert(VisitReservationTable visitReservationTable) {
        // 检查是否存在同一天、同一类型、同一时间段的记录
        VisitReservationTable existingReservation = visitReservationTableRepository
                .findByVisitDateAndReservationTypeAndVisitTimeSlot(
                        visitReservationTable.getVisitDate(),
                        visitReservationTable.getReservationType(),
                        visitReservationTable.getVisitTimeSlot()
                );

        if (existingReservation != null) {
            throw new DuplicateReservationException("同一天同一类型的场次在同一时间段已存在，请选择其他时间段");
        }

        return visitReservationTableRepository.save(visitReservationTable);
    }*/
  @Override
  public List<VisitReservationTable> insert(VisitReservationTable visitReservationTable) {
      // 确保传入的日期数组有效
      if (visitReservationTable.getDates() == null || visitReservationTable.getDates().length != 2) {
          throw new IllegalArgumentException("日期范围无效，请提供有效的开始时间和结束时间");
      }

      Date startDate = visitReservationTable.getDates()[0];
      Date endDate = visitReservationTable.getDates()[1];

      if (startDate.after(endDate)) {
          throw new IllegalArgumentException("开始日期不能晚于结束日期");
      }

      List<VisitReservationTable> insertedReservations = new ArrayList<>();
      Calendar calendar = Calendar.getInstance();
      calendar.setTime(startDate);

      // 遍历日期范围
      while (!calendar.getTime().after(endDate)) {
          Date currentVisitDate = calendar.getTime();

          // 检查是否存在同一天、同一类型、同一时间段的记录
          VisitReservationTable existingReservation = visitReservationTableRepository
                  .findByVisitDateAndReservationTypeAndVisitTimeSlot(
                          currentVisitDate,
                          visitReservationTable.getReservationType(),
                          visitReservationTable.getVisitTimeSlot()
                  );

          if (existingReservation != null) {
              throw new DuplicateReservationException("日期 " + currentVisitDate + " 同一类型的场次在同一时间段已存在，请选择其他时间段");
          }

          // 创建新的预约记录
          VisitReservationTable newReservation = new VisitReservationTable();
          newReservation.setReservationType(visitReservationTable.getReservationType());
          newReservation.setVisitDate(currentVisitDate);
          newReservation.setVisitTimeSlot(visitReservationTable.getVisitTimeSlot());
          newReservation.setReservedPeople(visitReservationTable.getReservedPeople());
          newReservation.setBookedPeople(visitReservationTable.getBookedPeople());
          newReservation.setRemainingSlots(visitReservationTable.getRemainingSlots());
          newReservation.setReservationStatus(visitReservationTable.getReservationStatus());
          newReservation.setRemainingSlots(visitReservationTable.getReservedPeople());
          newReservation.setBookedPeople(0);

          // 保存新记录
          insertedReservations.add(visitReservationTableRepository.save(newReservation));

          // 日期加一天
          calendar.add(Calendar.DATE, 1);
      }

      return insertedReservations;
  }


    @Override
    public VisitReservationTable update(VisitReservationTable visitReservationTable) {
        return visitReservationTableRepository.saveAndFlush(visitReservationTable);
    }

    @Override
    public void delete(Long id) {
        visitReservationTableRepository.deleteById(id);
    }


    @Override
    public VisitReservationTable handleReservation(Long visitId, Integer num) {
        // 查询唯一记录
        Optional<VisitReservationTable> reservationOptional = visitReservationTableRepository.findById(visitId);

        // 判断记录是否存在并进行相应处理
        if (reservationOptional.isPresent()) {
            VisitReservationTable reservation = reservationOptional.get();

            // 判断remainingSlots是否满足预定需求
            if (reservation.getRemainingSlots() - num >= 0) {
                // 更新已预定人数
                reservation.setBookedPeople(reservation.getBookedPeople() + num);
                // 更新剩余名额
                reservation.setRemainingSlots(reservation.getReservedPeople() - reservation.getBookedPeople());
                // 保存更新后的记录
                return visitReservationTableRepository.save(reservation);
            }
        }

        // 如果没有记录或名额不足，返回null
        return null;
    }

    /**
     * 根据日期和类型查询预约信息
     *
     * @param visitDate       预约日期
     * @param reservationType 预约类型
     * @return 符合条件的预约集合
     */
    @Override
    public List<VisitReservationTable> getReservationsByDateAndType(Date visitDate, String reservationType) {
        return visitReservationTableRepository.findByVisitDateAndReservationType(visitDate, reservationType);
    }

}